home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / Kibitz / Notation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  13.5 KB  |  544 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        notation.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1990-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __MEMORY__
  21. #include <Memory.h>
  22. #endif
  23.  
  24. #ifndef __RESOURCES__
  25. #include <Resources.h>
  26. #endif
  27.  
  28. #ifndef __TEXTEDITCONTROL__
  29. #include <TextEditControl.h>
  30. #endif
  31.  
  32. #ifndef __TOOLUTILS__
  33. #include <ToolUtils.h>
  34. #endif
  35.  
  36. #ifndef __UTILITIES__
  37. #include <Utilities.h>
  38. #endif
  39.  
  40.  
  41.  
  42. /*****************************************************************************/
  43.  
  44.  
  45.  
  46. #pragma segment Window
  47. Boolean    Algebraic(FileRecHndl frHndl, short doMoveNum, short gameIndex, StringPtr pstr)
  48. {
  49.     short            from, to, piece, extend, rowMatch, colMatch;
  50.     short            i, r, c, rr, cc, rrr, ccc, fff, ttt, ppp;
  51.     short            color, kingLoc;
  52.     GameListHndl    gameMoves;
  53.     MoveListHndl    legalMoves;
  54.  
  55.     gameMoves = (*frHndl)->doc.gameMoves;
  56.     from = (**gameMoves)[doMoveNum].moveFrom;
  57.     to   = (**gameMoves)[doMoveNum].moveTo;
  58.  
  59.     if (!from) {
  60.         GetIndString(pstr, rGameStat, to);
  61.         while (pstr[1] == ' ') BlockMove(pstr + 2, pstr + 1, --pstr[0]);
  62.         return(false);
  63.     }
  64.  
  65.     r  = from / 10;
  66.     c  = from - 10 * r - 1;
  67.     r -= 2;
  68.  
  69.     rr  = to / 10;
  70.     cc  = to - 10 * rr - 1;
  71.     rr -= 2;
  72.  
  73.     piece = (*frHndl)->doc.theBoard[from];
  74.     if (piece < 0) piece = -piece;
  75.  
  76.     pstr[0] = 0;
  77.     if (piece == PAWN) {
  78.         if (c != cc) {
  79.             pstr[++pstr[0]] = "abcdefgh"[c];
  80.             pstr[++pstr[0]] = 'x';
  81.         }
  82.     }
  83.     if (piece == KING) {
  84.         i = c - cc;
  85.         if (i == 2) {
  86.             pcpy(pstr, "\pO-O-O");
  87.             piece = EMPTY;
  88.         }
  89.         if (i == -2) {
  90.             pcpy(pstr, "\pO-O");
  91.             piece = EMPTY;
  92.         }
  93.     }
  94.  
  95.     if (piece > PAWN) {
  96.         rowMatch = colMatch = extend = false;
  97.         GenerateLegalMoves(frHndl);
  98.         legalMoves = (*frHndl)->doc.legalMoves;
  99.         for (i = 0; i < (*frHndl)->doc.numLegalMoves; ++i) {
  100.             fff = (**legalMoves)[i].moveFrom;
  101.             ttt = (**legalMoves)[i].moveTo;
  102.             if ((ttt == to) && (fff != from)) {
  103.                 ppp = (*frHndl)->doc.theBoard[fff];
  104.                 if (ppp < 0) ppp = -ppp;
  105.                 if (ppp != piece) continue;
  106.                 rrr  = fff / 10;
  107.                 ccc  = fff - 10 * rrr - 1;
  108.                 rrr -= 2;
  109.                 extend = true;
  110.                 if (r == rrr) rowMatch = true;
  111.                 if (c == ccc) colMatch = true;
  112.             }
  113.         }
  114.         if ((extend) && (!colMatch)) rowMatch |= extend;
  115.         pstr[++pstr[0]] = "  NBRQK"[piece];
  116.         if (rowMatch)
  117.             pstr[++pstr[0]] = "abcdefgh"[c];
  118.         if (colMatch)
  119.             pstr[++pstr[0]] = "87654321"[r];
  120.         i = (*frHndl)->doc.theBoard[to];
  121.         if ((i) && (i != OBNDS)) pstr[++pstr[0]] = 'x';
  122.  
  123.     }
  124.     if (piece) {
  125.         pstr[++pstr[0]] = "abcdefgh"[cc];
  126.         pstr[++pstr[0]] = "87654321"[rr];
  127.     }
  128.     if (piece == PAWN) {
  129.         if (to = (**gameMoves)[doMoveNum].promoteTo) {
  130.             if (to < 0) to = -to;
  131.             pstr[++pstr[0]] = '=';
  132.             pstr[++pstr[0]] = "  NBRQ"[to];
  133.         }
  134.     }
  135.  
  136.     if (doMoveNum < (*frHndl)->doc.numGameMoves) {
  137.         RepositionBoard(frHndl, doMoveNum + 1, false);
  138.         kingLoc = (*frHndl)->doc.king[color = WhosMove(frHndl)].kingLoc;
  139.         if (SquareAttacked(frHndl, kingLoc, color)) pstr[++pstr[0]] = '+';
  140.         RepositionBoard(frHndl, doMoveNum, false);
  141.     }
  142.  
  143.     return(doMoveNum == gameIndex - 1);
  144. }
  145.  
  146.  
  147.  
  148. /*****************************************************************************/
  149.  
  150.  
  151.  
  152. #pragma segment Menu
  153. void    MovesToOutBox(FileRecHndl frHndl, EventRecord *event)
  154. {
  155.     short        txtIndx, numGameMoves, gameIndex, startColor;
  156.     short        move, moveColor, moveNum, i, selStart, selEnd, condensed;
  157.     Boolean        needCR;
  158.     Str255        txt;
  159.     Handle        txtHndl;
  160.     TEHandle    teHndl;
  161.     WindowPtr    oldPort;
  162.  
  163.     txtHndl = NewHandle(32000);
  164.     if (!txtHndl) return;
  165.     txtIndx = 0;
  166.  
  167.     condensed = (event->modifiers & optionKey);
  168.  
  169.     numGameMoves = (*frHndl)->doc.numGameMoves;
  170.     gameIndex    = (*frHndl)->doc.gameIndex;
  171.     teHndl       = (*frHndl)->doc.message[kMessageOut];
  172.     startColor   = (*frHndl)->doc.startColor;
  173.  
  174.     txt[0] = 0;
  175.     needCR = false;
  176.     for (move = gameIndex; move < numGameMoves; ++move) {
  177.         moveColor = ((move + startColor) & 0x01);
  178.         moveNum   = ((move + startColor) / 2 + 1);
  179.         if ((needCR) && (!moveColor)) {
  180.             i = (condensed) ? 32 : 13;
  181.             (*txtHndl)[txtIndx++] = i;
  182.             needCR = false;
  183.         }
  184.         if ((!moveColor) || (move == gameIndex)) {
  185.             pcpydec(txt, i = (move / 2 + 1));
  186.             pcat(txt, "\p)  ");
  187.             if ((condensed) || (i > 9)) txt[0]--;
  188.             BlockMove(txt + 1, *txtHndl + txtIndx, txt[0]);
  189.             txtIndx += txt[0];
  190.             needCR = true;
  191.         }
  192.         if ((moveColor) && (move == gameIndex)) {
  193.             if (condensed) {
  194.                 BlockMove("...,", *txtHndl + txtIndx, 4);
  195.                 txtIndx += 4;
  196.             }
  197.             else {
  198.                 BlockMove("...      ", *txtHndl + txtIndx, 8);
  199.                 txtIndx += 8;
  200.             }
  201.             needCR = true;
  202.         }
  203.         RepositionBoard(frHndl, move, false);
  204.         Algebraic(frHndl, move, 0, txt);
  205.         if (move < numGameMoves - 1) {
  206.             if (condensed) {
  207.                 if (!moveColor) txt[++(txt[0])] = ',';
  208.             }
  209.             else {
  210.                 if (!moveColor) pcat(txt, "\p        ");
  211.                 if (txt[0] > 8) txt[0] = 8;
  212.             }
  213.         }
  214.         BlockMove(txt + 1, *txtHndl + txtIndx, txt[0]);
  215.         txtIndx += txt[0];
  216.         needCR = true;
  217.     }
  218.  
  219.     LockHandleHigh(txtHndl);
  220.     oldPort = SetFilePort(frHndl);
  221.  
  222.     CTENewUndo(CTEViewFromTE(teHndl), true);
  223.     TEDelete(teHndl);
  224.     selStart = (*teHndl)->selStart;
  225.     TEInsert(*txtHndl, txtIndx, teHndl);
  226.     selEnd = (*teHndl)->selStart;
  227.     TESetSelect(selStart, selEnd, teHndl);
  228.     TESelView(teHndl);
  229.     CTEAdjustTEBottom(teHndl);
  230.     CTEAdjustScrollValues(teHndl);
  231.     (*frHndl)->fileState.docDirty = true;
  232.  
  233.     SetPort(oldPort);
  234.     DisposHandle(txtHndl);
  235.  
  236.     RepositionBoard(frHndl, gameIndex, false);
  237. }
  238.  
  239.  
  240.  
  241. /*****************************************************************************/
  242.  
  243.  
  244.  
  245. #pragma segment Menu
  246. void    MovesFromOutBox(FileRecHndl frHndl)
  247. {
  248.     WindowPtr        oldPort;
  249.     TEHandle        teHndl;
  250.     Handle            txtHndl;
  251.     short            txtLen, selStart, selEnd, gameIndex, txtIndx, commentCount;
  252.     short            numUsed, numLglMoves, lastChar, c0, c1, i;
  253.     short            from, to, fromRow, fromCol, promoteTo, piece, f, t, r, c;
  254.     long            tick;
  255.     char            *cptr;
  256.     MoveListHndl    lglMoves;
  257.     static char        goodFirstFromChar[] = "Oo01abcdefghPNBRQK";
  258.  
  259.     oldPort  = SetFilePort(frHndl);
  260.     teHndl   = (*frHndl)->doc.message[kMessageOut];
  261.     txtHndl  = (*teHndl)->hText;
  262.     txtLen   = (*teHndl)->teLength;
  263.     selStart = (*teHndl)->selStart;
  264.     selEnd   = (*teHndl)->selEnd;
  265.     if (selEnd == selStart) selEnd = txtLen;
  266.  
  267.     GenerateLegalMoves(frHndl);
  268.     gameIndex = (*frHndl)->doc.gameIndex;
  269.     txtIndx = selStart;
  270.     commentCount = 0;
  271.  
  272.     tick = TickCount();
  273.  
  274.     for (;; txtIndx += numUsed) {
  275.  
  276.         if (!commentCount) {
  277.             numLglMoves = (*frHndl)->doc.numLegalMoves;
  278.             lglMoves    = (*frHndl)->doc.legalMoves;
  279.             if (!numLglMoves) break;
  280.                 /* Can't accept any moves, as there are no legal moves. */
  281.         }
  282.  
  283.         lastChar = selEnd - txtIndx - 1;
  284.         if (lastChar < 1) break;
  285.             /* An algebraic move is at least 2 characters. */
  286.  
  287.         cptr = *txtHndl + txtIndx;
  288.         c0 = cptr[0];
  289.         numUsed = 1;        /* Always use at least 1 character per pass. */
  290.  
  291.         if (c0 == '[') {
  292.             ++commentCount;
  293.             continue;
  294.         }
  295.  
  296.         if (c0 == ']') {
  297.             if (commentCount) --commentCount;
  298.             continue;
  299.         }
  300.  
  301.         if (commentCount) continue;
  302.  
  303.         for (i = 0; goodFirstFromChar[i]; ++i)
  304.             if (c0 == goodFirstFromChar[i]) break;
  305.         if (!goodFirstFromChar[i]) continue;
  306.             /* Not good first character, so check next char. */
  307.  
  308.         fromRow = fromCol = -1;
  309.         from = to = 0;
  310.             /* From may be square or piece. */
  311.             /* To will be square. */
  312.             /* If to stays 0, then to = from, and from = PAWN.  More on this later. */
  313.  
  314.         for (;;) {        /* Used to break from for jump purposes. */
  315.  
  316.             if (i < 3) {        /* First character is castling character... */
  317.                 if (lastChar < 2) break;
  318.                     /* Not enough characters for kside castling. */
  319.                 if (cptr[numUsed] != '-') break;        /* Isn't a castle. */
  320.                 if (cptr[numUsed + 1] != '1') {            /* Isn't a black-wins notation. */
  321.                     if (cptr[++numUsed] != c0) break;    /* Isn't a castle. */
  322.                     from = (WhosMove(frHndl)) ? 25 : 95;
  323.                     to   = from + 2;
  324.                     if (lastChar < 4) {
  325.                         ++numUsed;
  326.                         break;
  327.                     }        /* Not enough characters for qside castling, so try kside. */
  328.                     if (cptr[++numUsed] != '-') break;        /* Isn't a castle. */
  329.                     if (cptr[++numUsed] != c0) break;        /* Isn't a castle. */
  330.                     to -= 4;
  331.                     ++numUsed;
  332.                     break;        /* Try qside castle. */
  333.                 }
  334.             }
  335.  
  336.             i -= 2;
  337.             if (i < 2) {    /* May be end-of-game notation. (1-0, 1/2, 0-1) */
  338.                 if (lastChar < 2) break;
  339.                     /* Not enough characters for end-of-game notation. */
  340.                 c1 = cptr[numUsed];
  341.                 if (c1 == '-') {
  342.                     if (cptr[numUsed + 1] == ('1' - i)) to = kWhiteResigns + i;
  343.                 }
  344.                 else if (c1 == '/') {
  345.                     if (cptr[numUsed + 1] == '2') to = kDrawGame;
  346.                 }
  347.                 if (to) EndTheGame(frHndl, to);
  348.                 to = 0;
  349.                 break;        /* Done processing this character, either way. */
  350.             }
  351.  
  352.             i -= 2;
  353.             if (i < 8) {        /* It is probably a pawn move.  The form is one of */
  354.                                 /* the following: e4, dxe4, d3xe4, d3e4, d3-e4.    */
  355.                                 /* Due to this, it can't be decided yet as to      */
  356.                                 /* whether we are looking at the from or the to    */
  357.                                 /* location.                                       */
  358.  
  359.                 from = PAWN;
  360.                 fromCol = i;    /* Might end up the toCol, so keep this in mind. */
  361.                 c1 = cptr[numUsed];
  362.                 if ((c1 >= '1') && (c1 <= '8')) {
  363.                     fromRow = 7 - (c1 - '1');    /* Might end up the toRow. */
  364.                     if (++numUsed > lastChar) break;
  365.                     c1 = cptr[numUsed];
  366.                 }
  367.                 if ((c1 == 'x') || (c1 == 'X') || (c1 == '-')) {
  368.                     if (++numUsed > lastChar) break;
  369.                     c0 = cptr[numUsed];
  370.                     if ((c0 < 'a') || (c0 > 'h')) break;
  371.                     if (++numUsed > lastChar) break;
  372.                     c1 = cptr[numUsed];
  373.                     if ((c1 >= '1') && (c1 <= '8')) {
  374.                         to = 10 * (7 - (c1 - '1')) + (c0 - 'a') + START_IBNDS;
  375.                         from = PAWN;        /* Assume it is a pawn move. */
  376.                         if ((fromRow != -1) && (fromCol != -1))
  377.                             from = 10 * fromRow + fromCol + START_IBNDS;
  378.                                 /* Move is of form d3-e4, so it doesn't have to be a pawn. */
  379.                         ++numUsed;
  380.                         break;
  381.                     }
  382.                 }
  383.                 else {        
  384.                     if (fromRow != -1) {            /* Of the form e4. */
  385.                         if ((c1 < 'a') || (c1 > 'h')) {
  386.                             from = PAWN;
  387.                             to = 10 * fromRow + fromCol + START_IBNDS;
  388.                             fromRow = fromCol = -1;        /* No hint of where from. */
  389.                         }
  390.                         else {
  391.                             if (++numUsed > lastChar) break;
  392.                             c0 = c1;
  393.                             c1 = cptr[numUsed];
  394.                             if ((c1 >= '1') && (c1 <= '8')) {
  395.                                 to = 10 * (7 - (c1 - '1')) + (c0 - 'a') + START_IBNDS;
  396.                                 from = PAWN;        /* Assume it is a pawn move. */
  397.                                 if ((fromRow != -1) && (fromCol != -1))
  398.                                     from = 10 * fromRow + fromCol + START_IBNDS;
  399.                                         /* Move is of form d3e4, so it doesn't have to be a pawn. */
  400.                                 ++numUsed;
  401.                                 break;
  402.                             }
  403.                         }
  404.                     }
  405.                     break;
  406.                 }
  407.             }
  408.  
  409.             else from = i - 7;        /* Remember which kind of piece. */
  410.  
  411.             c0 = cptr[numUsed];
  412.  
  413.             if (c0 == '(') {    /* Parens are optional -- just skip them. */
  414.                 if (++numUsed > lastChar) break;
  415.                 c0 = cptr[numUsed];
  416.             }
  417.  
  418.             if ((c0 >= 'a') && (c0 <= 'h')) {
  419.                 fromCol = c0 - 'a';
  420.                 if (++numUsed > lastChar) break;
  421.                 c0 = cptr[numUsed];
  422.             }
  423.             if ((c0 >= 'a') && (c0 <= 'h')) {
  424.                 if (++numUsed > lastChar) break;
  425.                 c1 = cptr[numUsed];
  426.                 if ((c1 >= '1') && (c1 <= '8')) {
  427.                     to = 10 * (7 - (c1 - '1')) + (c0 - 'a') + START_IBNDS;
  428.                     ++numUsed;
  429.                 }
  430.                 break;
  431.             }
  432.             if ((c0 >= '1') && (c0 <= '8')) {
  433.                 fromRow = 7 - (c0 - '1');
  434.                 if (++numUsed > lastChar) break;
  435.                 c0 = cptr[numUsed];
  436.             }
  437.  
  438.             if (c0 == ')') {    /* Parens are optional -- just skip them. */
  439.                 if (++numUsed > lastChar) break;
  440.                 c0 = cptr[numUsed];
  441.             }
  442.  
  443.             if ((c0 == 'x') || (c0 == 'X') || (c0 == '-')) {
  444.                 if (++numUsed > lastChar) break;
  445.                 c0 = cptr[numUsed];
  446.             }
  447.  
  448.             if ((c0 >= 'a') && (c0 <= 'h')) {
  449.                 if (++numUsed > lastChar) break;
  450.                 c1 = cptr[numUsed];
  451.                 if ((c1 >= '1') && (c1 <= '8')) {
  452.                     to = 10 * (7 - (c1 - '1')) + (c0 - 'a') + START_IBNDS;
  453.                     ++numUsed;
  454.                 }
  455.                 break;
  456.             }
  457.             else {
  458.                 if ((fromRow != -1) && (fromCol != -1)) {
  459.                     to = 10 * fromRow + fromCol + START_IBNDS;
  460.                     fromRow = fromCol = -1;        /* No hint of where from. */
  461.                 }
  462.                 break;
  463.             }
  464.  
  465.             break;
  466.         }
  467.  
  468.         if (!to) {
  469.             if ((fromRow != -1) && (fromCol != -1)) {
  470.                 to = 10 * fromRow + fromCol + START_IBNDS;
  471.                 fromRow = fromCol = -1;
  472.             }
  473.         }
  474.  
  475.         promoteTo = QUEEN;
  476.         if (to) {
  477.             if (numUsed < lastChar) {
  478.                 if (cptr[numUsed++] == '=') {
  479.                     if (numUsed < lastChar) {
  480.                         c1 = cptr[numUsed++];
  481.                         if (c1 == 'N') promoteTo = KNIGHT;
  482.                         if (c1 == 'B') promoteTo = BISHOP;
  483.                         if (c1 == 'R') promoteTo = ROOK;
  484.                     }
  485.                 }
  486.             }
  487.         }
  488.  
  489.         i = numLglMoves;
  490.         for (i = 0; i < numLglMoves; ++i) {
  491.             f = (**lglMoves)[i].moveFrom;
  492.             t = (**lglMoves)[i].moveTo;
  493.             if (to != t) continue;
  494.             if (from >= START_IBNDS) {
  495.                 if (from == f) break;
  496.                 continue;
  497.             }
  498.             piece = (*frHndl)->doc.theBoard[f];
  499.             if (piece < 0) piece = -piece;
  500.             if (piece == from) {
  501.                 r = (f - START_IBNDS) / 10;
  502.                 c = f - START_IBNDS - 10 * r;
  503.                 if (fromRow == -1) r = -1;
  504.                 if (fromCol == -1) c = -1;
  505.                 if ((fromRow == r) && (fromCol == c)) {
  506.                     from = f;
  507.                     break;
  508.                 }
  509.             }
  510.         }
  511.         if (i < numLglMoves) {
  512.             MakeMove(frHndl, from, to, promoteTo);
  513.             GenerateLegalMoves(frHndl);
  514.             ImageDocument(frHndl, true);
  515.             AdjustGameSlider(frHndl);
  516.             UpdateGameStatus(frHndl);
  517.             if (tick + 30 < TickCount()) {        /* Send max 1 AppleEvent per 1/2 sec. */
  518.                 tick = TickCount();
  519.                 if ((*frHndl)->doc.twoPlayer) SendGame(frHndl, kScrolling, nil);
  520.             }
  521.         }
  522.         else {
  523.             if ((!from) && (!to)) {
  524.                 if (numUsed > 1) --numUsed;
  525.                 for (;;) {
  526.                     c0 = cptr[numUsed++];
  527.                     if (numUsed >= lastChar) break;
  528.                     if ((c0 >= 'A') && (c0 <= 'Z')) continue;
  529.                     if ((c0 >= 'a') && (c0 <= 'z')) continue;
  530.                     if ((c0 >= '0') && (c0 <= '9')) continue;
  531.                     break;
  532.                 }
  533.             }
  534.         }
  535.     }
  536.  
  537.     if ((*frHndl)->doc.twoPlayer) SendGame(frHndl, kResync, nil);
  538.  
  539. }
  540.  
  541.  
  542.  
  543.  
  544.